﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Framework
{
    public class Timer : MonoBehaviour
    {
        private int _timerId = 0;

        private void Awake()
        {
            Instance = this;
        }

        public static Timer Instance { get; private set; }

        private List<TimerHandler> timers = new List<TimerHandler>();
        public int DelayCall(float delay, Action callback)
        {
            _timerId++;
            long now = GetCurrentTime();
            long finishTime =  now + (long)delay*1000;
            TimerHandler handler = new TimerHandler(_timerId, finishTime, delay, null, callback);
            timers.Add(handler);
            return _timerId;
        }

        public int CountDown(float interval, Action<float> stepCallback, Action finishCallback, long finishTime = long.MaxValue)
        {
            _timerId++;
            TimerHandler handler = new TimerHandler(_timerId, finishTime, interval, stepCallback, finishCallback);
            timers.Add(handler);
            return _timerId;
        }

        public static long GetCurrentTime()
        {
            return DateTime.Now.Ticks / 10000L;
        }

        private void Update()
        {
            long now = GetCurrentTime();
            for (int i = timers.Count - 1; i >= 0; i--)
            {
                var handle = timers[i];
                bool isFinish = handle.TryExecute(Time.deltaTime, now);
                if (isFinish)
                {
                    timers.Remove(handle);
                }
            }
        }

        public void RemoveTimer(int id)
        {
            TimerHandler th = timers.Find(timer => { return timer.Id == id; });
            timers.Remove(th);
        }

        public void RemoveTimers(List<int> timerIds)
        {
            foreach (int timerId in timerIds)
            {
                RemoveTimer(timerId);
            }
        }
        
        public void Cleanup()
        {
            timers.Clear();
        }
    }

    public class TimerHandler
    {
        public int Id;
        private Action<float> stepFunction;
        private Action finishFunction;
        private float interval;
        private long finishTime;
        private float intervalTime;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="finishTime"></param>
        /// <param name="interval"></param>
        /// <param name="stepFunction">参数 剩余时间</param>
        /// <param name="finishFunction"></param>
        public TimerHandler(int id, long finishTime, float interval, Action<float> stepFunction, Action finishFunction)
        {
            Id = id;
            this.stepFunction = stepFunction;
            this.finishFunction = finishFunction;
            this.interval = interval;
            this.finishTime = finishTime;
            intervalTime = 0;
        }

        public bool TryExecute(float deltaTime, long now)
        {
            if (stepFunction != null)
            {
                //CountDown
                intervalTime += deltaTime;
                if (intervalTime >= interval)
                {
                    float remainingTime = finishTime - now;
                    intervalTime -= interval;
                    stepFunction(remainingTime);
                }
            }
            
            if (now >= finishTime)
            {
                finishFunction();
                return true;
            }

            return false;
        }
    }
}